/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable no-plusplus */
/* eslint-disable no-param-reassign */
/* eslint-disable no-continue */
import {
  IGlobalConfig,
  IResourceViewModel,
  IScheduleResource,
  IScheduleTask,
  ITaskViewModel,
} from "../interface";
import Variables from "../constant/vars";
import { UICoordinateController } from "./ui-coordinate.controller";
import { GlobalConfigController } from "./global-config.controller";

/**
 * @description 绘制图层控制器
 * @export
 * @class RenderLayerController
 */
export class RenderLayerController {
  /**
   * @description 全局配置
   * @private
   * @type {GlobalConfigController}
   * @memberof RenderLayerController
   */
  private configController!: GlobalConfigController;

  /**
   * @description 事件控制器
   * @private
   * @type {any}
   * @memberof RenderLayerController
   */
  private evt: any;

  /**
   * @description 资源
   * @type {IScheduleResource[]}
   * @memberof RenderLayerController
   */
  private resources: IScheduleResource[] = [];

  /**
   * @description 任务
   * @private
   * @type {IScheduleTask[]}
   * @memberof RenderLayerController
   */
  private tasks: IScheduleTask[] = [];

  /**
   * @description 资源视图模型
   * @type {IResourceViewModel[]}
   * @memberof RenderLayerController
   */
  resourceViewModels: IResourceViewModel[] = [];

  /**
   * @description 任务视图模型
   * @type {ITaskViewModel[]}
   * @memberof RenderLayerController
   */
  taskViewModels: ITaskViewModel[] = [];

  /**
   * Creates an instance of RenderLayerController.
   * @param {GlobalConfigController} configController
   * @param {IScheduleResource[]} resources
   * @param {IScheduleTask[]} tasks
   * @memberof RenderLayerController
   */
  constructor(
    configController: GlobalConfigController,
    evt: any,
    resources: IScheduleResource[],
    tasks: IScheduleTask[]
  ) {
    this.configController = configController;
    this.evt = evt;
    this.resources = resources;
    this.tasks = this.filterValidTasks(tasks);
  }

  /**
   * @description 获取资源
   * @readonly
   * @type {IScheduleResource[]}
   * @memberof RenderLayerController
   */
  getResources(): IScheduleResource[] {
    return this.resources;
  }

  /**
   * @description 设置资源
   * @param {IScheduleResource[]} resources
   * @memberof RenderLayerController
   */
  setResources(resources: IScheduleResource[]): void {
    this.resources = resources;
  }

  /**
   * @description 更新资源
   * - 如果已经存在则更新，不存在则新增
   * @param {IScheduleResource} resource
   * @memberof RenderLayerController
   */
  updateResource(resource: IScheduleResource): void {
    const index = this.resources.findIndex((res) => res.id === resource.id);
    index !== -1
      ? this.resources.splice(index, 1, resource)
      : this.resources.push(resource);
  }

  /**
   * @description 获取任务
   * @returns {*}  {IScheduleTask[]}
   * @memberof RenderLayerController
   */
  getTasks(): IScheduleTask[] {
    return this.tasks;
  }

  /**
   * @description 设置任务
   * @param {IScheduleTask[]} tasks
   * @memberof RenderLayerController
   */
  setTasks(tasks: IScheduleTask[]): void {
    this.tasks = this.filterValidTasks(tasks);
  }

  /**
   * @description 更新任务
   * - 如果已经存在则更新，不存在则新增
   * @param {IScheduleTask} task
   * @memberof RenderLayerController
   */
  updateTask(task: IScheduleTask): void {
    if (this.verifyTask(task)) {
      const index = this.tasks.findIndex((_task) => _task.id === task.id);
      index !== -1 ? this.tasks.splice(index, 1, task) : this.tasks.push(task);
    }
  }

  /**
   * @description 校验任务
   * @param {IScheduleTask} task
   * @returns {*}  {boolean}
   * @memberof RenderLayerController
   */
  verifyTask(task: IScheduleTask): boolean {
    const config = this.configController.getConfig();
    // 全局起止时间
    const startDate = new Date(config.startTime);
    startDate.setHours(0, 0, 0, 0);
    const endDate = new Date(config.endTime);
    endDate.setHours(0, 0, 0, 0);
    // 检查任务的开始时间和结束时间是否有效
    if (task.start >= task.end) return false;
    // 如果任务的结束时间小于全局开始时间，则任务无效
    if (task.end < startDate) return false;
    // 如果任务的开始时间大于全局结束时间，则任务无效
    if (task.start > endDate) return false;
    return true;
  }

  /**
   * @description 过滤有效任务
   * @param {IScheduleTask[]} tasks
   * @returns {*}  {IScheduleTask[]}
   * @memberof RenderLayerController
   */
  filterValidTasks(tasks: IScheduleTask[]): IScheduleTask[] {
    return tasks.filter(task => this.verifyTask(task));
  }

  /**
   * @description 构建资源视图模型
   * @private
   * @param {IGlobalConfig} config
   * @memberof RenderLayerController
   */
  private buildResourceViewModels(config: IGlobalConfig): void {
    const resourceViewModels: IResourceViewModel[] = [];
    if (this.resources.length > 0) {
      for (let i = 0; i < this.resources.length; i++) {
        const resource = this.resources[i];
        resourceViewModels.push({
          id: resource.id,
          width: config.resourceColumnWidth,
          height: config.resourceBodyRowHeight,
          top: i * config.resourceBodyRowHeight,
          left: 0,
          data: resource,
        });
      }
    }
    this.resourceViewModels = resourceViewModels;
  }

  /**
   * @description 检测任务冲突并分组
   * @private
   * @param {ITaskViewModel[]} taskViewModels 任务视图模型列表
   * @returns {ITaskViewModel[][]} 冲突任务分组
   * @memberof RenderLayerController
   */
  private groupConflictingTasks(
    taskViewModels: ITaskViewModel[]
  ): ITaskViewModel[][] {
    const groups: ITaskViewModel[][] = [];
    const visited = new Set<string>();

    taskViewModels.forEach((task) => {
      if (visited.has(task.id)) return;

      const group: ITaskViewModel[] = [task];
      visited.add(task.id);

      taskViewModels.forEach((otherTask) => {
        if (visited.has(otherTask.id) || task.id === otherTask.id) return;

        // 检查是否为同一资源
        if (task.resourceId !== otherTask.resourceId) return;

        // 检查时间是否重叠
        if (this.isTimeOverlapping(task, otherTask)) {
          group.push(otherTask);
          visited.add(otherTask.id);
        }
      });

      groups.push(group);
    });

    return groups;
  }

  /**
   * @description 检查两个任务的时间是否重叠
   * @private
   * @param {ITaskViewModel} task1 任务1
   * @param {ITaskViewModel} task2 任务2
   * @returns {boolean} 是否重叠
   * @memberof RenderLayerController
   */
  private isTimeOverlapping(
    task1: ITaskViewModel,
    task2: ITaskViewModel
  ): boolean {
    // 如果是同一原始任务的不同部分，则不认为是冲突
    if (task1.originalId === task2.originalId) {
      return false;
    }

    return (
      task1.left < task2.left + task2.width && // task1 的左边界在 task2 的右边界左侧
      task1.left + task1.width > task2.left && // task1 的右边界在 task2 的左边界右侧
      task1.top < task2.top + task2.height && // task1 的上边界在 task2 的下边界上方
      task1.top + task1.height > task2.top // task1 的下边界在 task2 的上边界下方
    );
  }

  /**
   * @description 处理冲突任务的显示位置
   * @private
   * @param {ITaskViewModel[][]} conflictGroups 冲突任务分组
   * @memberof RenderLayerController
   */
  private processConflictingTasks(conflictGroups: ITaskViewModel[][]): void {
    conflictGroups.forEach((group) => {
      if (group.length <= 1) return;

      // 按照top位置排序
      group.sort((a, b) => a.top - b.top);

      // 计算每项的宽度
      const singleWidth = group[0].width / group.length;

      // 调整每个任务的位置和宽度
      group.forEach((task: ITaskViewModel, index: number) => {
        task.width = singleWidth;
        task.left += index * singleWidth;
      });
    });
  }

  /**
   * @description 将跨天任务分割成每天的部分
   * @private
   * @param {IScheduleTask} task 原始任务
   * @param {IGlobalConfig} config 全局配置
   * @returns {IScheduleTask[]} 分割后的任务列表
   * @memberof RenderLayerController
   */
  private splitTaskByDays(
    task: IScheduleTask,
    config: IGlobalConfig
  ): IScheduleTask[] {
    const splitTasks: IScheduleTask[] = [];

    // 如果任务不跨天，直接返回原任务
    const taskStart = new Date(task.start);
    const taskEnd = new Date(task.end);

    // 如果开始和结束在同一天，不需要分割
    if (taskStart.toDateString() === taskEnd.toDateString()) {
      return [task];
    }

    // 分割跨天任务
    const currentStart = new Date(taskStart);
    let dayCounter = 0;

    while (currentStart < taskEnd) {
      // 计算当天的结束时间（23:59:59）
      const currentEnd = new Date(currentStart);
      currentEnd.setHours(23, 59, 59, 999);

      // 如果当前结束时间超过了任务结束时间，则使用任务结束时间
      if (currentEnd > taskEnd) {
        currentEnd.setTime(taskEnd.getTime());
      }

      // 创建分割后的任务
      const splitTask: IScheduleTask = {
        ...task,
        id: `${task.id}_part_${dayCounter}`,
        start: new Date(currentStart),
        end: new Date(currentEnd),
      };

      splitTasks.push(splitTask);

      // 设置下一天的开始时间（00:00:00）
      currentStart.setDate(currentStart.getDate() + 1);
      currentStart.setHours(0, 0, 0, 0);
      dayCounter++;
    }

    return splitTasks;
  }

  /**
   * @description 构建任务视图模型
   * @private
   * @param {IGlobalConfig} config
   * @param {UICoordinateController} uiCoordinate
   * @returns {*}  {void}
   * @memberof RenderLayerController
   */
  private buildTaskViewModels(
    config: IGlobalConfig,
    uiCoordinate: UICoordinateController
  ): void {
    if (!uiCoordinate) {
      return;
    }
    const taskViewModels: ITaskViewModel[] = [];
    if (this.tasks.length > 0) {
      // 计算时间范围内的天数
      const startDate = new Date(config.startTime);
      startDate.setHours(0, 0, 0, 0);
      const endDate = new Date(config.endTime);
      endDate.setHours(0, 0, 0, 0);
      for (let i = 0; i < this.tasks.length; i++) {
        const task = this.tasks[i];
        const resourceIndex = this.resources.findIndex(
          (resource) => resource.id === task.resourceId
        );
        if (resourceIndex === -1) {
          console.warn(
            `Task ${task.id} references non-existent resource ${task.resourceId}`
          );
          continue;
        }

        // 处理跨天任务，将其分割成多个部分
        const splitTasks = this.splitTaskByDays(task, config);

        splitTasks.forEach((splitTask) => {
          // 计算任务日期属性
          const taskStartDate = new Date(splitTask.start);
          taskStartDate.setHours(0, 0, 0, 0);
          const taskEndDate = new Date(splitTask.end);
          taskEndDate.setHours(0, 0, 0, 0);

          // 计算任务在日期轴上的位置
          const daysFromStart = Math.ceil(
            (taskStartDate.getTime() - startDate.getTime()) /
              Variables.time.millisecondOf.day
          );
          const left =
            config.resourceColumnWidth +
            config.scaleColumnWidth +
            daysFromStart * uiCoordinate.cellWidth;

          // 如果任务跨多天，计算宽度
          const taskDurationDays =
            Math.ceil(
              (taskEndDate.getTime() - taskStartDate.getTime()) /
                Variables.time.millisecondOf.day
            ) + 1;
          const width = taskDurationDays * uiCoordinate.cellWidth;

          // 计算任务在时间轴上的位置（垂直方向）
          const taskStartHour =
            splitTask.start.getHours() + splitTask.start.getMinutes() / 60;
          const top =
            resourceIndex * config.resourceBodyRowHeight +
            (taskStartHour - config.scaleRange[0]) *
              (uiCoordinate.cellHeight / config.scaleValue);
          // 计算任务高度
          const taskDurationHours =
            (splitTask.end.getTime() - splitTask.start.getTime()) /
            Variables.time.millisecondOf.hour;
          const height =
            taskDurationHours * (uiCoordinate.cellHeight / config.scaleValue);

          taskViewModels.push({
            id: splitTask.id,
            originalId: task.id,
            resourceId: splitTask.resourceId,
            width,
            height,
            top,
            left,
            data: splitTask,
          });
        });
      }
    }

    // 检测并处理冲突任务
    const conflictGroups = this.groupConflictingTasks(taskViewModels);
    this.processConflictingTasks(conflictGroups);

    this.taskViewModels = taskViewModels;
  }

  /**
   * @description 构建视图模型
   * @param {UICoordinateController} uiCoordinate
   * @memberof RenderLayerController
   */
  buildViewModels(uiCoordinate: UICoordinateController): void {
    // return new Promise(resolve => {
    //   const config = this.configController.getConfig();
    //   // 如果支持Web Workers且任务数量较多，则使用Web Worker
    //   // if (typeof Worker !== 'undefined' && this.tasks.length > 100) {
    //   if (typeof Worker !== 'undefined') {
    //     try {
    //       // 动态导入Web Worker
    //       const worker = new Worker(
    //         new URL('../workers/view-model.worker.ts', import.meta.url),
    //       );
    //       worker.onmessage = event => {
    //         this.resourceViewModels = event.data.resourceViewModels;
    //         this.taskViewModels = event.data.taskViewModels;
    //         worker.terminate();
    //         resolve();
    //       };

    //       worker.onerror = error => {
    //         console.error('Web Worker处理异常，由主线程处理:', error);
    //         worker.terminate();
    //         this.buildResourceViewModels(config);
    //         this.buildTaskViewModels(config, uiCoordinate);
    //         resolve();
    //       };

    //       // 发送可序列化的数据到Web Worker
    //       const serializableConfig = {
    //         startTime: config.startTime,
    //         endTime: config.endTime,
    //         headerRowHeight: config.headerRowHeight,
    //         headerBgColor: config.headerBgColor,
    //         headerTextColor: config.headerTextColor,
    //         resourceColumnWidth: config.resourceColumnWidth,
    //         resourceBodyRowHeight: config.resourceBodyRowHeight,
    //         resourceBodyBg: config.resourceBodyBg,
    //         resourceDriverColor: config.resourceDriverColor,
    //         scaleColumnWidth: config.scaleColumnWidth,
    //         scaleRange: config.scaleRange,
    //         scaleValue: config.scaleValue,
    //         scaleTextColor: config.scaleTextColor,
    //         scaleBodyBg: config.scaleBodyBg,
    //         gridLineColor: config.gridLineColor,
    //         allowDrag: config.allowDrag,
    //         dragInterval: config.dragInterval,
    //       };
    //       const serializableTasks = this.tasks.map(task => {
    //         return { ...task, data: { ...task.data } };
    //       });
    //       const serializableResources = this.resources.map(resource => {
    //         return { ...resource };
    //       });

    //       // 发送数据到Web Worker
    //       worker.postMessage({
    //         tasks: serializableTasks,
    //         resources: serializableResources,
    //         config: serializableConfig,
    //         uiCoordinateData: {
    //           cellWidth: uiCoordinate.cellWidth,
    //           cellHeight: uiCoordinate.cellHeight,
    //         },
    //       });
    //     } catch (error) {
    //       console.error('Web Worker构建异常，由主线程处理:', error);
    //       this.buildResourceViewModels(config);
    //       this.buildTaskViewModels(config, uiCoordinate);
    //       resolve();
    //     }
    //   } else {
    //     // 对于小数据集或不支持Web Workers的情况，直接在主线程处理
    //     this.buildResourceViewModels(config);
    //     this.buildTaskViewModels(config, uiCoordinate);
    //     resolve();
    //   }
    // });
    const config = this.configController.getConfig();
    this.buildResourceViewModels(config);
    this.buildTaskViewModels(config, uiCoordinate);
  }

  /**
   * @description 销毁
   * @memberof RenderLayerController
   */
  destory(): void {}
}
